from common.base.base_handler import BaseHandler
from services.dsp.model import Dsp
from services.dsp.schemas.configs import DspConfig, Delays,DspSubchannelsControl, DspModesConfig
from services.server_integration.schemas.service_channel_configuration import NbSubchannels
from settings import settings


class DspHandler(BaseHandler):
    __slots__ = ['model']


    async def handle_set_pilots_cycles(self, params: dict):
        cycles = params['cycles']
        self.model.set_cycles(cycles)

    async def handle_get_pilots_cycles(self):
        return self.model.get_cycles()

    async def handle_get_lo(self) -> list:
        return self.model.offsets_lo

    async def handle_set_lo(self, params: dict) -> bool:
        lo = params['value']
        index = params['index']
        self.model.offsets_lo[index] = lo
        for addr, value in zip(self.model.addresses, self.model.offsets_lo):
            await self.model._write_offsets(addr, value / 1_000_000.0)

        return True

    async def handle_get_reinit(self) -> bool:
        reinit = self.model.do_reinit
        self.model.do_reinit = False
        return reinit

    async def handle_set_reinit(self) -> bool:
        self.model.do_reinit = True
        return True

    async def handle_set_dsp_config(self, params: dict) -> bool:
        name, config, do_reinit = params['name'], DspConfig(**params['config']), params['do_reinit']
        if do_reinit:
            self.model.configs[name]['config'] = config

        await self.model.configure(name, self.model.configs, do_reinit, config)
        self.model.do_reinit = do_reinit
        return True

    async def handle_set_dsp_modes(self, params: dict) -> bool:
        modes = DspModesConfig(**params)
        self.model.set_dsp_modes(modes)

        return True

    async def handle_set_typical_coe(self, params: dict) -> bool:
        name, index, file_name = params['name'], params['index'], params['file_name']
        self.model.write_typical_coe_file(name, index, file_name)
        self.model.coe_configs[name][f'loaded_coe-{index}'] = file_name

        return True

    async def handle_set_custom_hex_coe(self, params: dict) -> bool:
        name, index, offset_bw_bands = params['name'], params['index'], params['offset_bw_bands']
        self.model.write_custom_hex_coe_file(name, index, offset_bw_bands)

        return True

    async def handle_set_channels_control(self, params: dict) -> bool:
        index, control = params['index'], DspSubchannelsControl(**params['control'])
        await self.model.set_subchannels_control(index, control)

        return True

    async def handle_set_delays_config(self, params: dict) -> bool:
        delay = Delays(**params)
        self.model.set_delays(delay)

        return True

    async def handle_get_dsp_config(self, params: dict) -> DspConfig:
        name = params['name']
        return self.model.configs[name]['config']

    async def handle_get_dsp_modes(self, params: dict) -> DspModesConfig:
        return self.model.get_dsp_modes()

    async def handle_get_coe(self, params: dict) -> str:
        name, index = params['name'], params['index']
        return self.model.coe_configs[name][f'loaded_coe-{index}']

    async def handle_get_channels_control(self, params: dict) -> DspSubchannelsControl:
        index = params['index']
        return self.model.subchannels_controls[index]

    async def handle_disable_calibration_config(self, params: dict) -> bool:
        for name in self.model.configs.keys():
            await self.model.configure(name, self.model.configs)

        for i in range(settings.DSP_NUMBER):
            i_p1 = i + 1
            loaded_coe = self.model.coe_configs['COE_UL_LNK_LNK'][f'loaded_coe-{i_p1}']
            self.model.write_typical_coe_file('COE_UL_LNK_LNK', i, loaded_coe)
            loaded_coe = self.model.coe_configs['COE_UL_SV_LNK'][f'loaded_coe-{i_p1}']
            self.model.write_typical_coe_file('COE_UL_SV_LNK', i, loaded_coe)
            loaded_coe = self.model.coe_configs['COE_DL_LNK_SV'][f'loaded_coe-{i_p1}']
            self.model.write_typical_coe_file('COE_DL_LNK_SV', i, loaded_coe)

        return True

    async def handle_enable_calibration_config(self, params: dict) -> bool:
        calibration_type = params['calibration_type']
        self.model.calibration_type = calibration_type

        calibration_config = getattr(self.model, f'{calibration_type}_calibration_config')
        for name in calibration_config.keys():
            await self.model.configure(name, calibration_config)

        coe_names = ['5MHz_191', '5MHz_191'] + ['5MHz'] * (settings.DSP_NUMBER - 2)
        for i in range(settings.DSP_NUMBER):
            self.model.write_typical_coe_file('COE_UL_LNK_LNK', i, coe_names[i])
            self.model.write_typical_coe_file('COE_UL_SV_LNK', i, coe_names[i])
            self.model.write_typical_coe_file('COE_DL_LNK_SV', i, coe_names[i])

        return True

    async def handle_calc_adfreq_subch_offsets(self, params: dict) -> bool:
        mode = params['mode']

        nb_subchannels2 = NbSubchannels(**params['nb_subchannels2'])
        nb_subchannels3 = NbSubchannels(**params['nb_subchannels3'])
        max_arfsn = params['max_arfsn']
        min_arfsn = params['min_arfsn']
        service_2_state = params['service_2_state']
        service_3_state = params['service_3_state']

        await self.model.write_subchannels_offsets_and_filters_crime(nb_subchannels2, nb_subchannels3, mode, max_arfsn, min_arfsn, service_2_state, service_3_state)

        return True

    async def handle_set_simulation_of_chain(self, params: dict) -> bool:
        state = params['state']
        self.model.set_simulation_of_chain(state)
        return True

    async def handle_get_simulation_of_chain(self) -> bool:
        return self.model.get_simulation_of_chain()

    async def handle_set_pilot_freq(self, params: dict):
        index, freq_rx, freq_tx = params['index'], params['freq_rx'], params['freq_tx']
        self.model.set_pilot_freq(index, freq_rx, freq_tx)

    async def handle_get_pilot_freq(self, params: dict):
        index = params['index']
        return self.model.get_pilot_freq(index)

    def __init__(self) -> None:
        self.model = Dsp(True)
        super(DspHandler, self).__init__(request_queue_uuid=settings.DSP_REQUEST_QUEUE)

        self.handle('set_pilots_cycles', self.handle_set_pilots_cycles)
        self.handle('get_pilots_cycles', self.handle_get_pilots_cycles)
        self.handle('get_dsp_config', self.handle_get_dsp_config)
        self.handle('set_dsp_config', self.handle_set_dsp_config)
        self.handle('get_coe', self.handle_get_coe)
        self.handle('set_typical_coe', self.handle_set_typical_coe)
        self.handle('set_custom_hex_coe', self.handle_set_custom_hex_coe)
        self.handle('disable_calibration_config', self.handle_disable_calibration_config)
        self.handle('enable_calibration_config', self.handle_enable_calibration_config)
        self.handle('set_delays_config', self.handle_set_delays_config)
        self.handle('set_dsp_modes', self.handle_set_dsp_modes)
        self.handle('get_dsp_modes', self.handle_get_dsp_modes)
        self.handle('set_channels_control', self.handle_set_channels_control)
        self.handle('get_channels_control', self.handle_get_channels_control)
        self.handle('get_reinit', self.handle_get_reinit)
        self.handle('set_reinit', self.handle_set_reinit)
        self.handle('calc_adfreq_subch_offsets', self.handle_calc_adfreq_subch_offsets)
        self.handle('set_simulation_of_chain', self.handle_set_simulation_of_chain)
        self.handle('get_simulation_of_chain', self.handle_get_simulation_of_chain)
        self.handle('get_lo', self.handle_get_lo)
        self.handle("set_pilot_freq", self.handle_set_pilot_freq)
        self.handle("get_pilot_freq", self.handle_get_pilot_freq)
